﻿#ifndef df_func_h__2013_12_10__0_10
#define df_func_h__2013_12_10__0_10


#include "df_macro.h"

namespace df
{
	template<typename... _Args>
	int Sprintf(char *string,
		size_t sizeInBytes,
		const char *format,
		_Args... args)
	{
		return DF_SPRINT_A(string, sizeInBytes, format, args...);
	}

	template<typename... _Args>
	int Sprintf(wchar_t *string,
		size_t sizeInBytes,
		const wchar_t *format,
		_Args... args)
	{
		return DF_SPRINT_W(string, sizeInBytes, format, args...);
	}




	///////////二进制转十进制
	template <typename TNum, unsigned long long _Num>
	struct Binary
	{
		static TNum const value = Binary<TNum, _Num / 10 >::value << 1 | _Num % 10;
	};

	template <typename TNum>
	struct Binary<TNum, 0>
	{
		static TNum const value = 0;
	};



	
	enum{
		//缓冲大小 4KB
		BUFFER_SIZE = (4 * 1024),
		//最大日志大小
		MAX_LOG_SIZE = 2 * 1024 * 1024,
	};
	///缓冲扩充倍数
	const float ENTEND_MUL = 1.5;




	////求最大值
	template<typename T>
	inline T Max(T && a1, T && a2) //-> decltype(std::forward<T>(a1))
	{
		return a1 < a2 ? a2 : a1;
	}

	template<typename T, typename... Args>
	inline T Max(T && a1, T && a2, Args && ... args)
	{
		return Max(Max(a1, a2), args...);
	}



	template<class _CharT>
	inline _CharT * CopyStr(_CharT * dest, const _CharT * source, size_t destSize)
	{
		if (dest == nullptr || source == nullptr)
			return nullptr;

		size_t newSize = std::char_traits<_CharT>::length(source);

		if (newSize > destSize - 1)
			newSize = destSize - 1;

		memcpy(dest, source, newSize*sizeof(TCHAR));
		dest[newSize] = 0;
		return dest;
	}



	//用于转换返回值类型
	template<typename _RetT>
	struct ConvertRetToBool
	{
		//非bool类型一律返回true
		template<class LamT, class... Args>
		inline static bool CB(LamT && lam, Args && ...args)
		{
			lam(std::forward<Args>(args)...);
			return true;
		}
	};
	template<>
	struct ConvertRetToBool<bool>
	{
		template<class LamT, class... Args>
		inline static bool CB(LamT && lam, Args && ...args)
		{
			return lam(std::forward<Args>(args)...);
		}
	};

	//用于转换std::function返回值类型
	template<typename _RetT>
	struct ConvertFuncRetToBool
	{
		//非bool类型一律返回true
		template<class LamT, class... Args>
		inline static bool CB(LamT && lam, Args && ...args)
		{
			if (lam)
				lam(std::forward<Args>(args)...);
			return true;
		}
	};
	template<>
	struct ConvertFuncRetToBool<bool>
	{
		template<class LamT, class... Args>
		inline static bool CB(LamT && lam, Args && ...args)
		{
			if (lam)
				return lam(std::forward<Args>(args)...);
			return true;
		}
	};

	

	//带参数执行函数func,将返回值类型统一为bool(当std::function为nullptr时也返回ture)
	template<class _LamT, class... _Args>
	inline bool ExecuteFunctor(const std::function<_LamT> & func, _Args && ...args)
	{
		return ConvertFuncRetToBool<decltype(func(args...))>::CB(func, std::forward<_Args>(args)...);
	}


	//带参数执行函数func,将返回值类型统一为bool
	template<class _LamT, class... _Args>
	inline bool ExecuteFunctor(_LamT && func, _Args && ...args)
	{
		return ConvertRetToBool<decltype(func(args...))>::CB(func, std::forward<_Args>(args)...);
	}



	//对pod类型单独赋值
	template<bool IsClass>
	struct AssignPOD
	{
		template<class T1, class... T2>
		static void Assign(T1 &, const T2 &...)
		{
		}
	};

	template<>
	struct AssignPOD<false>
	{
		template<class T1, class T2>
		static void Assign(T1 & v1, const T2 & v2)
		{
			v1 = v2;
		}
	};


};

#include "BaseChar.h"


namespace df
{
	///显示消息
	static inline void msg(const df::CCa & con, const df::CCa & tit = "消息")
	{
#ifdef WIN32
		MessageBoxA(GetActiveWindow(), con.char_, tit.char_, MB_ICONINFORMATION);
#else
		std::cout << con << " - " << tit << std::endl;
#endif
	}

	static inline void msg(const df::CCw & con, const df::CCw & tit = L"消息")
	{
#ifdef WIN32
		MessageBoxW(GetActiveWindow(), con.char_, tit.char_, MB_ICONINFORMATION);
#else
		std::wcout << con << L" - " << tit << std::endl;
#endif
	}

	static inline double StringToDouble(const df::BaseChar<char> & str)
	{
		return ::atof(str.char_);
	}

#ifdef _MSC_VER
	static inline double StringToDouble(const df::BaseChar<wchar_t> & str)
	{
		return ::_wtof(str.char_);
	}
#endif



	inline uint32_t GetError()
	{
#ifdef WIN32
		return ::GetLastError();
#else
		return (uint32_t)errno;
#endif // WIN32
	}



	inline TCHAR * CharBuffer()
	{
		static DF_THREAD_LOCAL_VAR TCHAR buf[df::BUFFER_SIZE];
		return buf;
	}



	inline size_t GetErrorString(uint32_t errnum, TCHAR *buf, size_t size)
	{
#ifdef WIN32
		return FormatMessage(
			//FORMAT_MESSAGE_ALLOCATE_BUFFER |
			FORMAT_MESSAGE_FROM_SYSTEM
			| FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			errnum,
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			buf,
			(DWORD)size,
			NULL);
#else
		if (strerror_r((int)errnum, buf, size) == 0)
			return strnlen(buf,size);
		else
			return 0;
#endif // WIN32
	}

	inline void GetErrorString(uint32_t errnum, String & str)
	{
		TCHAR buf[df::BUFFER_SIZE];
		size_t res = GetErrorString(errnum, buf, df::BUFFER_SIZE);
		if (res > 0)
		{
			str.append(buf, res);
		}

	}

	inline String GetErrorString()
	{
		String str;
		GetErrorString(GetError(), str);
		return str;
	}

	inline void GetErrorString(String & str)
	{
		GetErrorString(GetError(), str);
	}

	inline void ThreadSleep(int millisecond)
	{
#ifdef WIN32
		::Sleep(millisecond);
#else
		struct timespec short_wait;
		struct timespec remainder;
		short_wait.tv_sec = millisecond / 1000;
		short_wait.tv_nsec = (millisecond % 1000) * 1000 * 1000;
		::nanosleep(&short_wait, &remainder);
#endif
	}


	template<unsigned StartI, unsigned EndI>
	struct EachFunc
	{
		template<typename FuncT>
		static void Func(FuncT && cb)
		{
			cb.DF_TEMPLATE operator()<StartI>();

			EachFunc<StartI + 1, EndI>::Func(cb);
		}
	};

	template<unsigned EndI>
	struct EachFunc<EndI, EndI>
	{
		template<typename FuncT>
		static void Func(FuncT &&)
		{
		}
	};



}


#endif // df_func_h__2013_12_10__0_10
